--[[
  浙商银行ESB协议解析
]]
require("apm_core")
require("ApmXml")

local G_DEBUG = false

if G_DEBUG == false then
    function logDebug(fmt,...) end
    function logInfo(fmt,...) end
    function logWarn(fmt,...) end
    function logError(fmt,...) end
    function logFatal(fmt,...) end
end

local KRED='\x1B[0;31m'
local KSALMON='\x1B[1;31m'
local KGREEN='\x1B[0;32m'
local KLIMEGREEN='\x1B[1;32m'
local KYELLOW='\x1B[0;33m'
local KORANGE='\x1B[0;34m'
local KBLUE='\x1B[1;34m'
local KMAGENTA='\x1B[0;35m'
local KPINK='\x1B[1;35m'
local KCYAN='\x1B[0;36m'
local RESET='\x1B[0m'

local t_xml_tree
local s_soap_function
local s_rspcode
local s_rspmsg
local s_businessAcceptId

split = function(input, delimiter)
    input = tostring(input)
    delimiter = tostring(delimiter)
    if (delimiter=='') then return false end
    local pos,arr = 0, {}
    -- for each divider found
    for st,sp in function() return string.find(input, delimiter, pos, true) end do
        table.insert(arr, string.sub(input, pos, st - 1))
        pos = sp + 1
    end
    table.insert(arr, string.sub(input, pos))
    return arr
end

local function ip2long(ip)
    local ips = split(ip, ".")
    local num = 0
    for i,v in pairs(ips) do
        num = num + (tonumber(v) * math.pow(256,#ips-i))
    end
    return num
end

local function parseIp(ip)
    local _, _, value = string.find(ip, "(%d+.%d+)$")
    return value == nil and "" or value
end

local function protocol_detect(s_payload)
    if s_payload == nil then return false end

    t_xml_tree = ApmXml.load(s_payload, "UTF-8")

    return ApmXml.getValue(t_xml_tree, "/soapenv:Envelope") ~= nil or
            ApmXml.getValue(t_xml_tree, "/soap:Envelope") ~= nil or
            ApmXml.getValue(t_xml_tree, "/SOAP-ENV:Envelope") ~= nil
end

--- 解析请求
-- return
-- true: 解析成功; false: 解析失败
local function parse_request(ApmData)
    s_soap_function = ApmData.getField("request.soap.function", 1)
    if s_soap_function ~= nil then
        s_soap_function = string.gsub(s_soap_function, "Request", "")
    end

    s_businessAcceptId = ApmXml.getValue(t_xml_tree, ".//requestHeader/businessAcceptId/text()")
    if s_businessAcceptId == nil then
        s_businessAcceptId = ApmXml.getValue(t_xml_tree, ".//RequestHeader/businessAcceptId/text()")
    end

    return true
end

--- 解析响应
-- return
-- true: 解析成功; false: 解析失败
local function parse_response(ApmData)
    s_rspcode = ApmXml.getValue(t_xml_tree, ".//responseHeader/errorNo/text()")
    if s_rspcode == nil then
        s_rspcode = ApmXml.getValue(t_xml_tree, ".//ResponseHeader/errorNo/text()")
    end
    if s_rspcode == nil then
        s_rspcode = ApmXml.getValue(t_xml_tree, ".//ResponseBody/ResponseHeader_HS/ErrorNo/text()")
    end
    if s_rspcode == nil then
        s_rspcode = ApmXml.getValue(t_xml_tree, ".//returnCode/text()")
    end
    if s_rspcode == nil then
        local s = ApmXml.getValue(t_xml_tree, ".//responseHeader/errorNo")
        if s ~= nil then s_rspcode = "000000" end
    end
    if s_rspcode == nil then
        s_rspcode = ApmXml.getValue(t_xml_tree, ".//errCode/text()")
    end
    if s_rspcode == nil then
        s_rspcode = ApmXml.getValue(t_xml_tree, ".//action/actionFlag/text()")
		-- actionFlag = 0 or 1
		if s_rspcode ~= nil then s_rspcode = "000000" end
    end

    s_rspmsg = ApmXml.getValue(t_xml_tree, ".//responseHeader/errorInfo/text()")
    if s_rspmsg == nil then
        s_rspmsg = ApmXml.getValue(t_xml_tree, ".//ResponseBody/ResponseHeader_HS/ErrorInfo/text()")
    end
    if s_rspmsg == nil then
        s_rspmsg = ApmXml.getValue(t_xml_tree, ".//message/text()")
    end

    return true
end

-- return
function post_analysis()
    local ApmData = require("ApmData")
    if ApmData.getL7Proto() ~= 80 then return end
    if ApmData.getMsgType() ~= 1 then return end

    local s_soap_req
    local s_soap_resp

    s_soap_req = ApmData.getField("request.http.body.1", 1)
    if s_soap_req ~= nil then
        s_soap_req = string.trim(s_soap_req)
        if protocol_detect(s_soap_req) then
            parse_request(ApmData)
        end
    end

    s_soap_resp = ApmData.getField("response.http.body.1", 1)
    if s_soap_resp ~= nil then
        s_soap_resp = string.trim(s_soap_resp)
        if protocol_detect(s_soap_resp) then
            parse_response(ApmData)
        end
    end

	--logInfo("Request:["..KBLUE.."%s"..RESET.."]", s_soap_req)
	--logInfo("Response:["..KBLUE.."%s"..RESET.."]", s_soap_resp)

    if s_soap_function == nil then
        logInfo("s_soap_function is nil REQ:[%s]", s_soap_req)
    elseif s_rspcode == nil then
        logInfo("s_rspcode is nil RESP:[%s]", s_soap_resp)
    else
        ApmData.replaceField("transaction.type_code", s_soap_function)
        ApmData.replaceField("transaction.type_name", s_soap_function)
        ApmData.replaceField("transaction.title", s_soap_function)

        ApmData.replaceField("response.code_string", s_rspcode)
        ApmData.delFields("response.code")

        if s_rspmsg ~= nil then
            ApmData.replaceField("response.error_message", s_rspmsg)
        end

        if s_businessAcceptId ~= nil then
            ApmData.replaceField("transaction.code", s_businessAcceptId)
        end

        local i_src_ip = ip2long(ApmData.getSrcIp())
		local s_channel
		if (i_src_ip >= 168002049 and i_src_ip <= 168002054) then
			s_channel = "微信银行"
		elseif (i_src_ip >= 167802076 and i_src_ip <= 167802078)
			or (i_src_ip >= 167802072 and i_src_ip <= 167802074)
			or (i_src_ip >= 168002136 and i_src_ip <= 168002138)
			or (i_src_ip >= 168002140 and i_src_ip <= 168002142) then
			s_channel = "网上银行"
		elseif (i_src_ip >= 168002144 and i_src_ip <= 168002146)
			or (i_src_ip >= 167802080 and i_src_ip <= 167802082)
			or (i_src_ip >= 167801857 and i_src_ip <= 167801862) then
			s_channel = "直销银行"
		elseif i_src_ip == 167801863 or i_src_ip == 168002085
			or (i_src_ip >= 167802056 and i_src_ip <= 167802061)
			or (i_src_ip >= 167801870 and i_src_ip <= 167801871) then
			s_channel = "手机银行"
		elseif i_src_ip == 167772522 then
			s_channel = "自助"
		elseif i_src_ip == 167801928 or i_src_ip == 167802064
		    or i_src_ip == 167802066 or i_src_ip == 167801948
			or i_src_ip == 167802373 or i_src_ip == 167802378
			or i_src_ip == 167802018
			or (i_src_ip >= 167801924 and i_src_ip <= 167801925)
			or (i_src_ip >= 168002088 and i_src_ip <= 168002089)
			or (i_src_ip >= 167802020 and i_src_ip <= 167802022) then
			s_channel = "特色业务"
		end
		
		if s_channel ~= nil then
			ApmData.replaceField("transaction.channel_code", s_channel)
			ApmData.replaceField("transaction.channel_name", s_channel)
		end

        logInfo("ESB(%s:%d->%s:%d) name:%s|channel:%s|seq:%s|ret:%s|%s",
            ApmData.getSrcIp(),
            ApmData.getSrcPort(),
            parseIp(ApmData.getDstIp()),
            ApmData.getDstPort(),
            s_soap_function,
            s_channel,
            s_businessAcceptId,
            s_rspcode,
            s_rspmsg
        )
    end

    return
end
--ESB
--v1.0.6
